package hbase;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;


import org.apache.hadoop.hbase.regionserver.BloomType;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;


public class HbaseDemo {
    Table table = null;
    Connection conn = null;

    @Before
    public void getConn() throws IOException {
        //构建一个连接对象
        Configuration conf = HBaseConfiguration.create();  //会自动加载hbase-site.xml
        conf.set("hbase.zookeeper.quorum", "192.168.88.5:2181,192.168.88.6:2181,192.168.88.7:2181");
        conn = ConnectionFactory.createConnection(conf);
        table = conn.getTable(TableName.valueOf("t_user"));
    }
    /**
     * SQL语言共分为四大类：数据查询语言DQL，数据操纵语言DML，数据定义语言DDL，数据控制语言DCL
     * 1) DQL基本结构是由SELECT子句，FROM子句，WHERE子句组成的查询块
     * 2) DML主要有三种形式：插入：INSERT  更新：UPDATE  删除：DELETE
     * 3) DDL用来创建数据库中的各种对象-----表、视图、索引、同义词、聚簇等
     * 4) 数据控制语言DCL用来授予或回收访问数据库的某种特权，并控制数据库操纵事务发生的时间及效果，对数据库实行监视等。
     * <p>
     * <p>
     * DDL
     *
     * @throws IOException
     */
    /**
     * 添加表
     *
     * @throws IOException
     */
    @Test
    public void createTable() throws IOException {
        //从连接中构造一个DDL操作器
        Admin admin = conn.getAdmin();
        //创建一个表定义描述对象
        HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf("t_user"));
        //创建列族定义描述对象
        HColumnDescriptor hColumnDescriptor1 = new HColumnDescriptor("user");
        HColumnDescriptor hColumnDescriptor2 = new HColumnDescriptor("like");
        //设置该列族中存储数据的最大版本数，默认是1
        hColumnDescriptor1.setMaxVersions(3);
        //将列族定义信息对象放入表定义对象中
        hTableDescriptor.addFamily(hColumnDescriptor1);
        hTableDescriptor.addFamily(hColumnDescriptor2);
        //用DDL操作器对象：admin来建表
        admin.createTable(hTableDescriptor);
        //关闭连接
        admin.close();
        conn.close();
    }

    /**
     * 删除表
     */
    @Test
    public void testDropTable() throws IOException {
        //从连接中构造一个DDL操作器
        Admin admin = conn.getAdmin();
        //停用表
        admin.disableTable(TableName.valueOf("t_user"));
        //删除表
        admin.deleteTable(TableName.valueOf("t_user"));

        admin.close();
        conn.close();
    }

    /**
     * 修改表定义--添加一个列族
     */
    @Test
    public void testUpdateTable() throws IOException {
        //从连接中构造一个DDL操作器
        Admin admin = conn.getAdmin();
        //取出旧的表定义信息
        HTableDescriptor hTableDescriptor = admin.getTableDescriptor(TableName.valueOf("t_user"));
        //新构造一个列族定义
        HColumnDescriptor hColumnDescriptor = new HColumnDescriptor("eat");
        //设置该列族的布隆过滤器类型
        hColumnDescriptor.setBloomFilterType(BloomType.ROWCOL);
        //将列族定义添加到表定义对象中
        hTableDescriptor.addFamily(hColumnDescriptor);
        //将修改过的表定义交给admin去提交
        admin.modifyTable(TableName.valueOf("t_user"), hTableDescriptor);

        admin.close();
        conn.close();
    }

    /**
     * DML  数据的增删改查
     * <p>
     * 添加一条数据
     */
    @Test
    public void insert() throws IOException {
        Put put = new Put(Bytes.toBytes("001"));
        put.addColumn(Bytes.toBytes("user"), Bytes.toBytes("name"),Bytes.toBytes("zhangsan"));
        put.addColumn(Bytes.toBytes("user"), Bytes.toBytes("age"), Bytes.toBytes("25"));
        table.put(put);
        System.out.println("添加成功！！");
    }

    /**
     *
     * 批量添加数据
     */
    @Test
    public void insertList() throws IOException {
        List<Put> list = new ArrayList<Put>();
        for (int i = 1; i < 50; i++) {
            Put put = new Put(Bytes.toBytes("1" + i));
            put.addColumn(Bytes.toBytes("user"), Bytes.toBytes("name"), Bytes.toBytes("wangwu" + i));
            put.addColumn(Bytes.toBytes("user"), Bytes.toBytes("password"), Bytes.toBytes("1234" + i));
            list.add(put);
        }
        table.put(list);
    }
    /**
     *  修改数据 相同 rowkey 列簇 column 会覆盖新值
     */
    @Test
    public void update() throws IOException {
        Put put = new Put(Bytes.toBytes("002"));
        put.addColumn(Bytes.toBytes("user"), Bytes.toBytes("name"), Bytes.toBytes("wangwu"));
        put.addColumn(Bytes.toBytes("user"), Bytes.toBytes("age"), Bytes.toBytes("25"));
        table.put(put);
    }
    /**
     * 删除数据
     */
    @Test
    public void delete() throws IOException {
        //按行键删除
        Delete delete = new Delete(Bytes.toBytes("001"));
        table.delete(delete);
        //按列族删除
        Delete delete1 = new Delete(Bytes.toBytes("002"));
        delete1.addFamily(Bytes.toBytes("user"));
        table.delete(delete1);
        //按cell删除
        Delete delete2 = new Delete(Bytes.toBytes("002"));
        delete2.addColumn(Bytes.toBytes("user"),Bytes.toBytes("name"));
        table.delete(delete2);
        System.out.println("删除成功！！");
    }
    /**
     * 查询数据
     */
    @Test
    public void select() throws IOException {
        Get get = new Get(Bytes.toBytes("001"));
        Result result = table.get(get);
        System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("user"),Bytes.toBytes("name"))));
        System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("user"),Bytes.toBytes("age"))));
    }
    /**
     * 扫描数据
     */
    @Test
    public void scan() throws IOException {
          Scan scan = new Scan();
//        scan.addFamily(Bytes.toBytes("user"));

        // 扫描cell指定
        scan.addFamily(Bytes.toBytes("user"));
        Bytes.toBytes("name");
        // 按rowkey字典序扫描
        scan.addFamily(Bytes.toBytes("user"));
        Bytes.toBytes("age");

        ResultScanner scanner = table.getScanner(scan);
        for (Result result : scanner) {
            System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("user"), Bytes.toBytes("name"))));
            System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("user"), Bytes.toBytes("age"))));
        }
    }

}
